/*
 * Copyright (C) 2008-2011 CBDP Consortium
 * 
 * All rights reserved.
 *
 * This software is licensed as described in the file COPYING, which
 * you should have received as part of this distribution.
 * 
 * This software consists of contributions made by many individuals, 
 * listed below:
 *
 * Author: 	Xabier Laiseca <xabier.laiseca@deusto.es>
 * 			David Ausín <david.ausin@deusto.es>
 */
package cbdp.server.contextreasoner.impl.reasoner.jena;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

import cbdp.server.contextreasoner.exceptions.ReasonerException;
import cbdp.server.contextreasoner.impl.reasoner.RuleSet;

import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.InfModel;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.reasoner.rulesys.GenericRuleReasoner;
import com.hp.hpl.jena.reasoner.rulesys.Rule;
import com.hp.hpl.jena.reasoner.rulesys.Rule.ParserException;
import com.hp.hpl.jena.shared.Lock;

/**
 * @author  Xabier Laiseca (University of Deusto)
 */
public class JenaRuleSet implements RuleSet
{
	private final static String CANNOT_LOAD_RULES_EXCEPTION_MESSAGE = "The rules cannot be loaded.";
	
	
	private GenericRuleReasoner reasoner;
	private OntModel ontModel;
	private InputStream rules;
	
	
	/**
	 * @param ontModel
	 * @uml.property  name="ontModel"
	 */
	@Override
	public void setOntModel(final OntModel ontModel)
	{
		this.ontModel = ontModel;
	}
	
	/**
	 * @param rules
	 * @uml.property  name="rules"
	 */
	@Override
	public void setRules(final InputStream rules)
	{
		this.rules = rules;
	}

	@Override
	public void load() throws ReasonerException
	{
		final BufferedReader reader = new BufferedReader(new InputStreamReader(rules));

		try
		{
			reasoner = new GenericRuleReasoner(Rule.parseRules(Rule.rulesParserFromReader(reader)));
		}
		catch(final ParserException e)
		{
			throw new ReasonerException(CANNOT_LOAD_RULES_EXCEPTION_MESSAGE, e);
		}
	}

	@Override
	public boolean launch()
	{
		ontModel.enterCriticalSection(Lock.WRITE);
		
		try
		{
			final InfModel inferred = ModelFactory.createInfModel(reasoner, ontModel);
			
			if (!inferred.isEmpty())
			{
				final Model deductions = inferred.getDeductionsModel();			
				ontModel.add(deductions);
				
				return true;
			}
			else return false;
		}
		finally
		{
			ontModel.leaveCriticalSection();
		}
	}

	@Override
	public void destroy() {}

}
